home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
drdobbs
/
1991
/
03
/
c_progrm.asc
< prev
next >
Wrap
Text File
|
1991-02-15
|
19KB
|
798 lines
_C PROGRAMMING COLUMN_
by Al Stevens
[LISTING ONE]
/* ----------- keys.h ------------ */
#define TRUE 1
#define FALSE 0
#define ESC 27
#define F2 188
#define UP 200
#define FWD 205
#define DN 208
#define BS 203
int getkey(void);
int keyhit(void);
void curr_cursor(int *, int *);
void cursor(int, int);
void hidecursor(void);
void unhidecursor(void);
void savecursor(void);
void restorecursor(void);
void set_cursor_type(unsigned);
#define normalcursor() set_cursor_type(0x0607)
[LISTING TWO]
/* ----------- getkey.c ---------- */
#include <bios.h>
#include <dos.h>
#include "keys.h"
#define KEYBOARD 0x16
#define ZEROFLAG 0x40
#define SETCURSORTYPE 1
#define SETCURSOR 2
#define READCURSOR 3
#define HIDECURSOR 0x20
static unsigned video_mode;
static unsigned video_page;
static int cursorpos;
static int cursorshape;
/* ---- Test for keystroke ---- */
int keyhit(void)
{
_AH = 1;
geninterrupt(KEYBOARD);
return (_FLAGS & ZEROFLAG) == 0;
}
/* ---- Read a keystroke ---- */
int getkey(void)
{
int c;
while (keyhit() == 0)
;
if (((c = bioskey(0)) & 0xff) == 0)
c = (c >> 8) | 0x80;
else
c &= 0xff;
return c;
}
static void videoint(void)
{
static unsigned oldbp;
_DI = _DI;
oldbp = _BP;
geninterrupt(0x10);
_BP = oldbp;
}
void videomode(void)
{
_AH = 15;
videoint();
video_mode = _AL;
video_page = _BX;
video_page &= 0xff00;
video_mode &= 0x7f;
}
/* ---- Position the cursor ---- */
void cursor(int x, int y)
{
videomode();
_DX = ((y << 8) & 0xff00) + x;
_AX = 0x0200;
_BX = video_page;
videoint();
}
/* ---- get cursor shape and position ---- */
static void near getcursor(void)
{
videomode();
_AH = READCURSOR;
_BX = video_page;
videoint();
}
/* ---- Get current cursor position ---- */
void curr_cursor(int *x, int *y)
{
getcursor();
*x = _DL;
*y = _DH;
}
/* ---- Hide the cursor ---- */
void hidecursor(void)
{
getcursor();
_CH |= HIDECURSOR;
_AH = SETCURSORTYPE;
videoint();
}
/* ---- Unhide the cursor ---- */
void unhidecursor(void)
{
getcursor();
_CH &= ~HIDECURSOR;
_AH = SETCURSORTYPE;
videoint();
}
/* ---- Save the current cursor configuration ---- */
void savecursor(void)
{
getcursor();
cursorshape = _CX;
cursorpos = _DX;
}
/* ---- Restore the saved cursor configuration ---- */
void restorecursor(void)
{
videomode();
_DX = cursorpos;
_AH = SETCURSOR;
_BX = video_page;
videoint();
set_cursor_type(cursorshape);
}
/* ----------- set the cursor type -------------- */
void set_cursor_type(unsigned t)
{
videomode();
_AH = SETCURSORTYPE;
_BX = video_page;
_CX = t;
videoint();
}
[LISTING THREE]
/* ------------- mouse.h ------------- */
#ifndef MOUSE_H
#define MOUSE_H
#define MOUSE 0x33
int mouse_installed(void);
int mousebuttons(void);
void get_mouseposition(int *x, int *y);
void set_mouseposition(int x, int y);
void show_mousecursor(void);
void hide_mousecursor(void);
int button_releases(void);
void intercept_mouse(void);
void restore_mouse(void);
void resetmouse(void);
#define leftbutton() (mousebuttons()&1)
#define rightbutton() (mousebuttons()&2)
#define waitformouse() while(mousebuttons());
#endif
[LISTING FOUR]
/* ------------- mouse.c ------------- */
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <string.h>
#include "mouse.h"
static void mouse(int m1,int m2,int m3,int m4)
{
_DX = m4;
_CX = m3;
_BX = m2;
_AX = m1;
geninterrupt(MOUSE);
}
/* ---------- reset the mouse ---------- */
void reset_mouse(void)
{
mouse(0,0,0,0);
}
/* ----- test to see if the mouse driver is installed ----- */
int mouse_installed(void)
{
unsigned char far *ms;
ms = MK_FP(peek(0, MOUSE*4+2), peek(0, MOUSE*4));
return (ms != NULL && *ms != 0xcf);
}
/* ------ return true if mouse buttons are pressed ------- */
int mousebuttons(void)
{
int bx = 0;
if (mouse_installed()) {
mouse(3,0,0,0);
bx = _BX;
}
return bx & 3;
}
/* ---------- return mouse coordinates ---------- */
void get_mouseposition(int *x, int *y)
{
if (mouse_installed()) {
int mx, my;
mouse(3,0,0,0);
mx = _CX;
my = _DX;
*x = mx/8;
*y = my/8;
}
}
/* -------- position the mouse cursor -------- */
void set_mouseposition(int x, int y)
{
if(mouse_installed())
mouse(4,0,x*8,y*8);
}
/* --------- display the mouse cursor -------- */
void show_mousecursor(void)
{
if(mouse_installed())
mouse(1,0,0,0);
}
/* --------- hide the mouse cursor ------- */
void hide_mousecursor(void)
{
if(mouse_installed())
mouse(2,0,0,0);
}
/* --- return true if a mouse button has been released --- */
int button_releases(void)
{
int ct = 0;
if(mouse_installed()) {
mouse(6,0,0,0);
ct = _BX;
}
return ct;
}
static int mx, my;
/* ----- intercept the mouse in case an interrupted program is using it ---- */
void intercept_mouse(void)
{
if (mouse_installed()) {
_AX = 3;
geninterrupt(MOUSE);
mx = _CX;
my = _DX;
_AX = 31;
geninterrupt(MOUSE);
}
}
/* ----- restore the mouse to the interrupted program ----- */
void restore_mouse(void)
{
if (mouse_installed()) {
_AX = 32;
geninterrupt(MOUSE);
_CX = mx;
_DX = my;
_AX = 4;
geninterrupt(MOUSE);
}
}
[LISTING FIVE]
/* ----------- message.h ------------ */
#ifndef MESSAGES_H
#define MESSGAES_H
#define MAXMESSAGES 50
/* --------- event message codes ----------- */
enum messages {
START,
STOP,
KEYBOARD,
RIGHT_BUTTON,
LEFT_BUTTON,
MOUSE_MOVED,
BUTTON_RELEASED,
CURRENT_MOUSE_CURSOR,
MOUSE_CURSOR,
SHOW_MOUSE,
HIDE_MOUSE,
KEYBOARD_CURSOR,
CURRENT_KEYBOARD_CURSOR,
VIDEO_CHAR,
PUT_VIDEORECT,
GET_VIDEORECT
};
/* ------- defines a screen rectangle ------ */
typedef struct {
int x, y, x1, y1;
} RECT;
/* ------ integer type for message parameters ----- */
typedef int PARAM;
void post_message(enum messages, PARAM, PARAM);
int send_message(enum messages, PARAM, PARAM);
int dispatch_message(int (*)(enum messages, PARAM, PARAM));
RECT rect(int, int, int, int);
#endif
[LISTING SIX]
/* --------- message.c ---------- */
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include "mouse.h"
#include "keys.h"
#include "message.h"
static int mouse_event(void);
static int px = -1, py = -1;
static int mx, my;
static int first_dispatch = TRUE;
static struct msgs {
enum messages msg;
PARAM p1;
PARAM p2;
} msg_queue[MAXMESSAGES];
static int qonctr;
static int qoffctr;
static int (*mproc)(enum messages,int,int);
/* ----- post a message and parameters to msg queue ---- */
void post_message(enum messages msg, PARAM p1, PARAM p2)
{
msg_queue[qonctr].msg = msg;
msg_queue[qonctr].p1 = p1;
msg_queue[qonctr].p2 = p2;
if (++qonctr == MAXMESSAGES)
qonctr = 0;
}
/* --------- clear the message queue --------- */
static void clear_queue(void)
{
px = py = -1;
mx = my = 0;
first_dispatch = TRUE;
qonctr = qoffctr = 0;
}
/* ------ collect events into the message queue ------ */
static int collect_messages(void)
{
/* ---- collect any unqueued messages ---- */
enum messages event;
if (first_dispatch) {
first_dispatch = FALSE;
reset_mouse();
show_mousecursor();
send_message(START,0,0);
}
if ((event = mouse_event()) != 0)
post_message(event, mx, my);
if (keyhit())
post_message(KEYBOARD, getkey(), 0);
return qoffctr != qonctr;
}
int send_message(enum messages msg, PARAM p1, PARAM p2)
{
int rtn = 0;
RECT rc;
if (mproc == NULL)
return -1;
if (mproc(msg, p1, p2)) {
switch (msg) {
case STOP:
hide_mousecursor();
clear_queue();
mproc = NULL;
break;
/* -------- keyboard messages ------- */
case KEYBOARD_CURSOR:
unhidecursor();
cursor(p1, p2);
break;
case CURRENT_KEYBOARD_CURSOR:
curr_cursor((int*)p1,(int*)p2);
break;
/* -------- mouse messages -------- */
case SHOW_MOUSE:
show_mousecursor();
break;
case HIDE_MOUSE:
hide_mousecursor();
break;
case MOUSE_CURSOR:
set_mouseposition(p1, p2);
break;
case CURRENT_MOUSE_CURSOR:
get_mouseposition((int*)p1,(int*)p2);
break;
/* ----------- video messages ----------- */
case VIDEO_CHAR:
gettext(p1+1, p2+1, p1+1, p2+1, &rtn);
rtn &= 255;
break;
case PUT_VIDEORECT:
rc = *(RECT *) p1;
puttext(rc.x+1, rc.y+1, rc.x1+1, rc.y1+1,(char *) p2);
break;
case GET_VIDEORECT:
rc = *(RECT *) p1;
gettext(rc.x+1, rc.y+1, rc.x1+1, rc.y1+1,(char *) p2);
break;
default:
break;
}
}
return rtn;
}
/* ---- dispatch messages to the message proc function ---- */
int dispatch_message(
int (*msgproc)(enum messages msg,PARAM p1,PARAM p2))
{
mproc = msgproc;
/* ------ dequeue the next message ----- */
if (collect_messages()) {
struct msgs mq = msg_queue[qoffctr];
send_message(mq.msg, mq.p1, mq.p2);
if (++qoffctr == MAXMESSAGES)
qoffctr = 0;
if (mq.msg == STOP)
return FALSE;
}
return TRUE;
}
/* ---------- gather and interpret mouse events -------- */
static int mouse_event(void)
{
get_mouseposition(&mx, &my);
if (mx != px || my != py) {
px = mx;
py = my;
return MOUSE_MOVED;
}
if (button_releases())
return BUTTON_RELEASED;
if (rightbutton())
return RIGHT_BUTTON;
if (leftbutton())
return LEFT_BUTTON;
return 0;
}
/* ----------- make a RECT from coordinates --------- */
RECT rect(int x, int y, int x1, int y1)
{
RECT rc;
rc.x = x;
rc.y = y;
rc.x1 = x1;
rc.y1 = y1;
return rc;
}
[LISTING SEVEN]
/* ---------------- copyscrn.c -------------- */
#include <stdio.h>
#include <stdlib.h>
#include "keys.h"
#include "message.h"
static int message_proc(enum messages, int, int);
static void near highlight(RECT);
static void writescreen(RECT);
static void near setstart(int *, int, int);
static void near forward(int);
static void near backward(int);
static void near upward(int);
static void near downward(int);
static void init_variables(void);
static int cursorx, cursory; /* Cursor position */
static int mousex, mousey; /* Mouse cursor position */
static RECT blk;
static int kx = 0, ky = 0;
static int px = -1, py = -1;
static int mouse_marking = FALSE;
static int keyboard_marking = FALSE;
static int marked_block = FALSE;
static FILE *fp;
#ifdef TSR
#define main tsr_program
#endif
/* ---------- enter here to run screen grabber --------- */
void main(void)
{
fp = fopen("grab.dat", "wt");
if (fp != NULL) {
/* ----- event message dispatching loop ---- */
while(dispatch_message(message_proc))
;
fclose(fp);
}
}
/* --------- event-driven message processing function ------- */
static int message_proc(
enum message message, /* message */
int param1, /* 1st parameter */
int param2) /* 2nd parameter */
{
int mx = param1;
int my = param2;
int key = param1;
switch (message) {
case START:
init_variables();
post_message(CURRENT_KEYBOARD_CURSOR,(PARAM) &cursorx, (PARAM) &cursory);
post_message(KEYBOARD_CURSOR, 0, 0);
post_message(CURRENT_MOUSE_CURSOR,(PARAM) &mousex, (PARAM) &mousey);
post_message(MOUSE_CURSOR, 0, 0);
break;
case KEYBOARD:
switch (key) {
case FWD:
if (kx < 79) {
if (keyboard_marking)
forward(1);
kx++;
}
break;
case BS:
if (kx) {
if (keyboard_marking)
backward(1);
--kx;
}
break;
case UP:
if (ky) {
if (keyboard_marking)
upward(1);
--ky;
}
break;
case DN:
if (ky < 24) {
if (keyboard_marking)
downward(1);
ky++;
}
break;
case F2:
mouse_marking = FALSE;
setstart(&keyboard_marking, kx, ky);
break;
case '\r':
post_message(STOP, TRUE, 0);
break;
case ESC:
post_message(STOP, FALSE, 0);
break;
}
send_message(KEYBOARD_CURSOR, kx, ky);
break;
case LEFT_BUTTON:
if (!mouse_marking) {
px = mx;
py = my;
keyboard_marking = FALSE;
setstart(&mouse_marking, mx, my);
}
break;
case MOUSE_MOVED:
if (mouse_marking) {
if (px < mx)
forward(mx-px);
if (mx < px)
backward(px-mx);
if (py < my)
downward(my-py);
if (my < py)
upward(py-my);
px = mx;
py = my;
}
break;
case BUTTON_RELEASED:
mouse_marking = FALSE;
break;
case RIGHT_BUTTON:
post_message(STOP, TRUE, 0);
break;
case STOP:
if (marked_block) {
highlight(blk);
if (param1)
writescreen(rect(min(blk.x, blk.x1),min(blk.y, blk.y1),
max(blk.x, blk.x1),max(blk.y, blk.y1)));
}
send_message(MOUSE_CURSOR, mousex, mousey);
send_message(KEYBOARD_CURSOR, cursorx, cursory);
init_variables();
break;
default:
break;
}
return TRUE;
}
/* ------- set the start of block marking ------- */
static void near setstart(int *marking, int x, int y)
{
if (marked_block)
highlight(blk); /* turn off old block */
marked_block = FALSE;
*marking ^= TRUE;
blk.x1 = blk.x = x; /* set the corners of the new block */
blk.y1 = blk.y = y;
if (*marking)
highlight(blk); /* turn on the new block */
}
/* ----- move the block rectangle forward one position ----- */
static void near forward(int n)
{
marked_block = TRUE;
while (n-- > 0) {
if (blk.x < blk.x1)
highlight(rect(blk.x,blk.y,blk.x,blk.y1));
else
highlight(rect(blk.x+1,blk.y,blk.x+1,blk.y1));
blk.x++;
}
}
/* ---- move the block rectangle backward one position ----- */
static void near backward(int n)
{
marked_block = TRUE;
while (n-- > 0) {
if (blk.x > blk.x1)
highlight(rect(blk.x,blk.y,blk.x,blk.y1));
else
highlight(rect(blk.x-1,blk.y,blk.x-1,blk.y1));
--blk.x;
}
}
/* ----- move the block rectangle up one position ----- */
static void near upward(int n)
{
marked_block = TRUE;
while (n-- > 0) {
if (blk.y > blk.y1)
highlight(rect(blk.x,blk.y,blk.x1,blk.y));
else
highlight(rect(blk.x,blk.y-1,blk.x1,blk.y-1));
--blk.y;
}
}
/* ----- move the block rectangle down one position ----- */
static void near downward(int n)
{
marked_block = TRUE;
while (n-- > 0) {
if (blk.y < blk.y1)
highlight(rect(blk.x,blk.y,blk.x1,blk.y));
else
highlight(rect(blk.x,blk.y+1,blk.x1,blk.y+1));
blk.y++;
}
}
/* ------ write the rectangle to the file ------- */
static void writescreen(RECT rc)
{
int vx = rc.x;
int vy = rc.y;
while (vy != rc.y1+1) {
if (vx == rc.x1+1) {
fputc('\n', fp);
vx = rc.x;
vy++;
}
else {
fputc(send_message(VIDEO_CHAR, vx, vy), fp);
vx++;
}
}
}
/* ------- simple swap macro ------ */
#define swap(a,b) {int s=a;a=b;b=s;}
/* -------- invert the video of a defined rectangle ------- */
static void near highlight(RECT rc)
{
int *bf, *bf1, bflen;
if (rc.x > rc.x1)
swap(rc.x,rc.x1);
if (rc.y > rc.y1)
swap(rc.y,rc.y1);
bflen = (rc.y1-rc.y+1) * (rc.x1-rc.x+1) * 2;
if ((bf = malloc(bflen)) != NULL) {
send_message(HIDE_MOUSE, 0, 0);
send_message(GET_VIDEORECT, (PARAM) &rc, (PARAM) bf);
bf1 = bf;
bflen /= 2;
while (bflen--)
*bf1++ ^= 0x7700;
send_message(PUT_VIDEORECT, (PARAM) &rc, (PARAM) bf);
send_message(SHOW_MOUSE, 0, 0);
free(bf);
}
}
/* ---- initialize global variables for later popup ---- */
static void init_variables(void)
{
mouse_marking = keyboard_marking = FALSE;
kx = ky = blk.x = blk.y = blk.x1 = blk.y1 = 0;
px = py = -1;
mouse_marking = FALSE;
keyboard_marking = FALSE;
marked_block = FALSE;
}